﻿using System.Collections;
using System.Collections.Generic;
using shaco.Base;
using UnityEngine;

namespace ShootMan.NetEvent
{
    static public class NetHelper
    {
        static public void WriteHeaderAndBody(shaco.Base.DataBuffer data, HeaderData header, INetEvent body)
        {
            data.Clear();

            //写入header
            data.WriteInt(0);//刚开始还不知道body长度，先写一个int站位
            data.WriteInt((int)header.messageID);
            data.WriteString(header.uuid);

            //写入body
            body.WriteBody(data);

            //计算body长度并重新写入body
            data.Seek(0, System.IO.SeekOrigin.Begin);
            header.dataLength = data.GetLength() - header.headerLength;
            data.WriteInt(header.dataLength);
            data.Seek(0, System.IO.SeekOrigin.End);
        }

        static public HeaderData ReadHeader(shaco.Base.DataBuffer data)
        {
            data.Seek(0, System.IO.SeekOrigin.Begin);
            var retValue = new HeaderData();
            retValue.dataLength = data.ReadInt();
            retValue.messageID = (GameDefines.NetMesssageID)data.ReadInt();
            retValue.uuid = data.ReadString();
            return retValue;
        }

        static public void ReadHeaderAndBody(shaco.Base.DataBuffer data, out HeaderData header, out INetEvent body)
        {
            //读取header
            header = ReadHeader(data);

            //读取body
            body = shaco.Base.Utility.Instantiate(NetEvent.NetHelper.GetC2SEventTypeName(header.messageID)) as NetEvent.INetEvent;
            if (null != body)
                body.ReadBody(data);
            else
                shaco.Log.Error("NetHelper ReadHeaderAndBody error: invalid message id=" + header.messageID);
        }

        static public string GetC2SEventTypeName(GameDefines.NetMesssageID messageID)
        {
            return string.Format("ShootMan.NetEvent.C2S_{0}", messageID);
        }

        static public string GetS2CEventTypeName(GameDefines.NetMesssageID messageID)
        {
            return string.Format("ShootMan.NetEvent.S2C_{0}", messageID);
        }
    }

    public struct HeaderData : shaco.Base.Net.IHeaderInfo
    {
        static string _cacheUUID;
        public int headerLength
        {
            get
            {
                if (string.IsNullOrEmpty(_cacheUUID))
                    _cacheUUID = NewUUID();
                return sizeof(int) + sizeof(GameDefines.NetMesssageID) + sizeof(uint) + _cacheUUID.Length;
            }
        }
        public int dataLength { get; set; }
        public GameDefines.NetMesssageID messageID;
        public string uuid;

        static public string NewUUID()
        {
            return System.Guid.NewGuid().ToString();
        }
    }

    //测试消息
    public class C2S_Test : C2S_INetEvent
    {
        public GameDefines.NetMesssageID messageID { get { return GameDefines.NetMesssageID.Test; } }
        public string message = string.Empty;

        public void ReadBody(DataBuffer data)
        {
            message = data.ReadString();
        }

        public void WriteBody(shaco.Base.DataBuffer data)
        {
            data.WriteString(message);
        }
    }
    public class S2C_Test : C2S_Test
    {
       
    }

    //登陆游戏
    public class C2S_Login : C2S_INetEvent
    {
        public GameDefines.NetMesssageID messageID { get { return GameDefines.NetMesssageID.Login; } }

        virtual public void ReadBody(DataBuffer data)
        {
        }

        virtual public void WriteBody(shaco.Base.DataBuffer data)
        {
        }
    }
    public class S2C_Login : C2S_Login
    {
        public string playerID = "10086";

        override public void ReadBody(shaco.Base.DataBuffer data)
        {
            data.Seek(0, System.IO.SeekOrigin.Begin);
            playerID = data.ReadString();
        }

        override public void WriteBody(shaco.Base.DataBuffer data)
        {
            var uuid = HeaderData.NewUUID();
            data.WriteString(uuid);
        }
    }

    //通知其他玩家当前角色位置
    public class C2S_NotifySelfPosition : C2S_INetEvent
    {
        public GameDefines.NetMesssageID messageID { get { return GameDefines.NetMesssageID.NotifySelfPosition; } }
        public string playerID;
        public Vector3 position;

        public void ReadBody(shaco.Base.DataBuffer data)
        {
            playerID = data.ReadString();
            position.x = data.ReadFloat();
            position.y = data.ReadFloat();
            position.z = data.ReadFloat();
        }

        public void WriteBody(shaco.Base.DataBuffer data)
        {
            data.WriteString(playerID);
            data.WriteFloat(position.x);
            data.WriteFloat(position.y);
            data.WriteFloat(position.z);
        }
    }
    public class S2C_NotifySelfPosition : C2S_NotifySelfPosition, S2C_INotifyEventType
    {
        public void WriteNotifyData(INetEvent data)
        {
            var datTmp = data as C2S_NotifySelfPosition;
            if (null == datTmp)
            {
                shaco.Log.ErrorFormat("S2C_NotifySelfPosition WriteNotifyData erorr: not type '{0}'", typeof(C2S_NotifySelfPosition).FullName);
                return;
            }

            this.playerID = datTmp.playerID;
            this.position.x = datTmp.position.x;
            this.position.y = datTmp.position.y;
            this.position.z = datTmp.position.z;
        }
    }

    //通知其他玩家发射了子弹
    public class C2S_NotifySelfShoot : C2S_INetEvent
    {
        public GameDefines.NetMesssageID messageID { get { return GameDefines.NetMesssageID.NotifySelfShoot; } }
        public string playerID;
        public int shootCount;

        public void ReadBody(shaco.Base.DataBuffer data)
        {
            playerID = data.ReadString();
            shootCount = data.ReadInt();
        }

        public void WriteBody(shaco.Base.DataBuffer data)
        {
            data.WriteString(playerID);
            data.WriteInt(shootCount);
        }
    }
    public class S2C_NotifySelfShoot : C2S_NotifySelfShoot, S2C_INotifyEventType
    {
        public void WriteNotifyData(INetEvent data)
        {
            var datTmp = data as C2S_NotifySelfShoot;
            if (null == datTmp)
            {
                shaco.Log.ErrorFormat("S2C_NotifySelfShoot WriteNotifyData erorr: not type '{0}'", typeof(C2S_NotifySelfShoot).FullName);
                return;
            }

            this.playerID = datTmp.playerID;
            this.shootCount = datTmp.shootCount;
        }
    }

    //通知所有玩家产生一个敌人
    public class C2S_NotifySpawnEnemy : C2S_INetEvent
    {
        public GameDefines.NetMesssageID messageID { get { return GameDefines.NetMesssageID.NotifySpawnEnemy; } }
        public string playerID = "";
        public string enemyPrefabName = string.Empty;
        public Vector3 position = Vector3.zero;

        public void ReadBody(shaco.Base.DataBuffer data)
        {
            playerID = data.ReadString();
            enemyPrefabName = data.ReadString();
            position.x = data.ReadFloat();
            position.y = data.ReadFloat();
            position.z = data.ReadFloat();
        }

        public void WriteBody(shaco.Base.DataBuffer data)
        {
            data.WriteString(playerID);
            data.WriteString(enemyPrefabName);
            data.WriteFloat(position.x);
            data.WriteFloat(position.y);
            data.WriteFloat(position.z);
        }
    }

    public class S2C_NotifySpawnEnemy : C2S_NotifySpawnEnemy, S2C_INotifyEventType
    {
        public void WriteNotifyData(INetEvent data)
        {
            var datTmp = data as C2S_NotifySpawnEnemy;
            if (null == datTmp)
            {
                shaco.Log.ErrorFormat("S2C_NotifySpawnEnemy WriteNotifyData erorr: not type '{0}'", typeof(C2S_NotifySpawnEnemy).FullName);
                return;
            }

            this.playerID = datTmp.playerID;
            this.enemyPrefabName = datTmp.enemyPrefabName;
            this.position = datTmp.position;
        }
    }
}